import coin.exchange.base.kr_rest.level_book as level_book_mdl
import coin.exchange.base.kr_rest.public_client_base as pubcb
import coin.exchange.coinone_v2.kr_rest.native_public_client as npubc
from coin.exchange.coinone_v2.kr_rest.product import CoinoneProduct

from coin.proto.coin_market_query_pb2 import ProductTicker, ExchangeTicker


class CoinoneFeedParser(object):
  @staticmethod
  def parse_native_ticker(update_msg, product):
    assert update_msg['result'] == 'success'
    assert update_msg['errorCode'] == '0'
    return ProductTicker(high=float(update_msg['high']),
                         low=float(update_msg['low']),
                         last=float(update_msg['last']),
                         volume_24hr=float(update_msg['volume']),
                         exchange_timestamp=int(float(update_msg['timestamp']) * 1e+9),
                         native_symbol=product.native_symbol,
                         symbol=product.symbol)

  @staticmethod
  def parse_exchange_ticker(update_msg):
    assert update_msg['result'] == 'success'
    assert update_msg['errorCode'] == '0'
    product_ticker_list = []
    for currency, info in update_msg.items():
      if not isinstance(info, dict):
        continue
      product = CoinoneProduct.FromStrNativeProductNothrow(currency)
      if product is None:
        continue

      product_ticker = ProductTicker(high=float(update_msg[currency]['high']),
                                     low=float(update_msg[currency]['low']),
                                     last=float(update_msg[currency]['last']),
                                     volume_24hr=float(update_msg[currency]['volume']),
                                     exchange_timestamp=int(float(update_msg['timestamp']) * 1e+9),
                                     native_symbol=product.native_symbol,
                                     symbol=product.symbol)
      product_ticker_list.append(product_ticker)
    assert len(product_ticker_list) > 0
    return ExchangeTicker(exchange="Coinone", each_ticker=product_ticker_list)

  @staticmethod
  def parse_level_book(update_msg, product):
    level_book = level_book_mdl.LevelBook(product)
    for elem in update_msg['ask']:
      level_elem = level_book_mdl.LevelElement(float(elem['price']), float(elem['qty']), 0)
      level_book.add_ask(level_elem)
    for elem in update_msg['bid']:
      level_elem = level_book_mdl.LevelElement(float(elem['price']), float(elem['qty']), 0)
      level_book.add_bid(level_elem)
    level_book.finalize()
    return level_book


class CoinonePublicClient(pubcb.PublicClientBase):
  def __init__(self):
    self.npubc = npubc.CoinoneNativePublicClient()

  def query_ticker_impl(self, product):
    symbol = product.native_symbol
    update = self.npubc.get_ticker(symbol)
    update.msg = CoinoneFeedParser.parse_native_ticker(update.msg, product)
    return update

  def query_exchange_ticker_impl(self):
    update = self.npubc.get_ticker('ALL')
    update.msg = CoinoneFeedParser.parse_exchange_ticker(update.msg)
    return update

  def query_level_book_impl(self, product):
    symbol = product.native_symbol
    update = self.npubc.get_orderbook(symbol)
    update.msg = CoinoneFeedParser.parse_level_book(update.msg, product)
    return update


if __name__ == '__main__':
  client = CoinonePublicClient()
  update = client.query_exchange_ticker()
  print(update.msg)
